﻿// --------------------------------------------------------------------------------------------------------------------
// <copyright file="StorageService.cs" company="XamlNinja">
//   2011 Richard Griffin and Ollie Riches
// </copyright>
// <summary>
//   The storage service.
// </summary>
// --------------------------------------------------------------------------------------------------------------------

namespace WP7Contrib.Services.Storage
{
    using System.Collections.Generic;
    using System.Linq;
    using System.Linq.Expressions;
    using System.Reflection;
    using Common.Helpers;
    using Logging;
    using global::Serialization;


    /// <summary>
    /// Storage service, uses SiverlightSerializer internally, all types being stored using this service must
    /// support serialization via the SilverlightSerializer.
    /// </summary>
    public sealed class StorageService : IStorageService
    {
        /// <summary>
        /// The logger used to capture diagnostics information.
        /// </summary>
        private readonly ILog log;

        /// <summary>
        /// Initializes a new instance of the <see cref="StorageService"/> class.
        /// </summary>
        /// <param name="serialisationAssemblies">
        /// Assemblies requiring registration with the SilverlightSerializer.
        /// </param>
        public StorageService(IEnumerable<Assembly> serialisationAssemblies) : this(serialisationAssemblies, new DebugLog())
        {
        }


        /// <summary>
        /// Initializes a new instance of the <see cref="StorageService"/> class.
        /// </summary>
        /// <param name="serialisationAssemblies">
        /// Assemblies requiring registration with the SilverlightSerializer.
        /// </param>
        /// <param name="log">
        /// The logger used to capture diagnostics information.
        /// </param>
        public StorageService(IEnumerable<Assembly> serialisationAssemblies, ILog log)
        {
            this.log = log;
            SilverlightSerializer.RegisterSerializationAssembly(this.GetType().Assembly);

            serialisationAssemblies.ToList().ForEach(a =>
            {
                this.log.Write("StorageService: Registering assembly, name - '{0}'", a.FullName);
                SilverlightSerializer.RegisterSerializationAssembly(a);
            });
        }

        /// <summary>
        /// Opens an instance of the persistent storage, the contents will not survive an application restart.
        /// </summary>
        /// <param name="name">
        /// The context for the storage, e.g. view model name
        /// </param>
        /// <returns>
        /// Returns an instance of the persistent storage.
        /// </returns>
        public IStorage OpenPersistent(string name)
        {
            this.log.Write("StorageService: OpenPersistent, name - '{0}'", name);
            
            return new PersistentStorage(this.log, name);
        }

        /// <summary>
        /// Opens an instance of the persistent storage, the contents will not survive an application restart.
        /// </summary>
        /// <param name="expression">
        /// An expression used to express the name of the context for the storage, e.g. '() =&gt; MyPropertyName'
        /// </param>
        /// <typeparam name="T">
        /// The type contained in the expression.
        /// </typeparam>
        /// <returns>
        /// Returns an instance of the persistent storage.
        /// </returns>
        public IStorage OpenPersistent<T>(Expression<System.Func<T>> expression)
        {
            var name = ExpressionHelper.ExpressionName(expression);
            this.log.Write("StorageService: OpenPersistent, name - '{0}'", name);
            
            return new PersistentStorage(this.log, name);
        }

        /// <summary>
        /// Opens an instance of the transient storage, the contents will not survive an application restart.
        /// </summary>
        /// <param name="name">
        /// The context for the storage, e.g. view model name
        /// </param>
        /// <returns>
        /// Returns an instance of the transient storage.
        /// </returns>
        public IStorage OpenTransient(string name)
        {
            this.log.Write("StorageService: OpenTransient, name - '{0}'", name);

            return new TransientStorage(this.log, name);
        }

        /// <summary>
        /// Opens an instance of the transient storage, the contents will not survive an application restart.
        /// </summary>
        /// <param name="expression">
        /// An expression used to express the name of the context for the storage, e.g. '() =&gt; MyPropertyName'
        /// </param>
        /// <typeparam name="T">
        /// The type contained in the expression.
        /// </typeparam>
        /// <returns>
        /// Returns an instance of the transient storage.
        /// </returns>
        public IStorage OpenTransient<T>(Expression<System.Func<T>> expression)
        {
            var name = ExpressionHelper.ExpressionName(expression);
            this.log.Write("StorageService: OpenTransient, name - '{0}'", name);

            return new TransientStorage(this.log, ExpressionHelper.ExpressionName(expression));
        }
    }
}